package com.dingwen.treasure.base.util;

import lombok.Getter;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 　OptimizeUtil: 代码调试优化工具：参考Spring StopWatch 的拓展优化
 * 　@author dingwen
 * 　@since  2022/8/28
 */
@Slf4j
@UtilityClass
public class OptimizeUtils {


    /**
     * 任务优化数据集合
     */
    public static ConcurrentHashMap<String, Optimize> OPTIMIZES;

    static {
        OPTIMIZES = new ConcurrentHashMap<>();
    }

    /**
     * 开始
     *
     * @param taskId 任务id
     */
    public  void start(String taskId) {
        Optimize optimize = getOptimize(taskId);
        optimize.start();
    }

    /**
     * 停止
     *
     * @param taskId 任务id
     */
    public  void stop(String taskId) {
        Optimize optimize = getOptimize(taskId);
        optimize.stop();
    }

    /**
     * 得到消耗时间
     *
     * @param taskId 任务id
     * @return {@link Long}
     */
    public  Long getConsumeTime(String taskId) {
        Optimize optimize = getOptimize(taskId);
        return optimize.getConsumeTime();
    }

    /**
     * 得到执行次数
     *
     * @param taskId 任务id
     * @return {@link Integer}
     */
    public  Integer getCount(String taskId) {
        Optimize optimize = getOptimize(taskId);
        return optimize.getCount();
    }


    /**
     * 清除所有
     */
    public  void clear() {
        OPTIMIZES.clear();
    }

    /**
     * 重置
     *
     * @param taskId 任务id
     */
    public  void reset(String taskId) {
        Optimize optimize = getOptimize(taskId);
        optimize.reset();
    }


    /**
     * 复位,开始
     *
     * @param taskId 任务id
     */
    public  void resetAndStart(String taskId) {
        Optimize optimize = getOptimize(taskId);
        optimize.reset();
        optimize.start();
    }

    /**
     * 打印
     *
     * @param taskId 任务id
     */
    public  void print(String taskId, Logger logger) {
        Optimize optimize = getOptimize(taskId);
        logger.info("---------------------------------------------------------------------------------------------------");
        logger.info("---------------------------------------------------------------------------------------------------");
        logger.info("------任务名称：{}                                                ", taskId);
        logger.info("------耗   时：{}                                                ", optimize.getConsumeTime());
        logger.info("------执行次数：{}                                                ", optimize.getCount());
        logger.info("---------------------------------------------------------------------------------------------------");
        logger.info("---------------------------------------------------------------------------------------------------\n");
    }

    /**
     * 打印所有
     */
    public  void print(Logger logger) {
        for (String s : OPTIMIZES.keySet()) {
            print(s,logger);
        }
    }


    /**
     * 得到优化数据
     *
     * @param taskId 任务Id
     * @return {@link Optimize}
     */
    private  Optimize getOptimize(String taskId) {
        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        try {
            if (OPTIMIZES.containsKey(taskId)) {
                return OPTIMIZES.get(taskId);
            }
            Optimize optimize = new Optimize();
            OPTIMIZES.put(taskId, optimize);
            return optimize;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 数据持有对象： 静态内部类
     *
     * @author dingwen
     * @since  2022/08/28
     */
    public static class Optimize {

        /**
         * 开始时间
         */
        private Long startTime;


        /**
         * 消耗时间
         */
        @Getter
        private long consumeTime;

        /**
         * 消耗时间
         */
        @Getter
        private int count;

        /**
         * 开始
         */
        public void start() {
            this.startTime = System.currentTimeMillis();
        }

        /**
         * 停止
         */
        public void stop() {
            if (Objects.isNull(this.startTime)) {
                throw new RuntimeException("start() and stop() 必须成对出现");
            }
            // 当前任务耗时
            long currentConsumeTime = System.currentTimeMillis() - this.startTime;
            // 总任务耗时
            this.consumeTime += currentConsumeTime;
            // 代码块执行次数
            ++this.count;
        }

        /**
         * 重置
         */
        public void reset() {
            this.count = 0;
            this.consumeTime = 0L;
            this.startTime = 0L;
        }

    }
}
